﻿using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using XchangeStreamer.Utilities;

namespace XchangeStreamer.CacheServer.Core
{
    public class Server : IDisposable
    {
        #region Private Fields

        private static Server server;
        private Engine engine;
        private ServiceHost serviceHost;

        #endregion

        #region Const.

        private Server()
        {
            this.engine = new Engine();
            this.serviceHost = new ServiceHost(this.engine, new System.Uri("http://localhost:6003/CacheServer"), 
                                                            new System.Uri("net.pipe://localhost/CacheServer"), 
                                                            new System.Uri("net.tcp://localhost:7003/CacheServer"));

            serviceHost.AddServiceEndpoint("XchangeStreamer.Core.CacheServer.ISender", Settings.TcpBinding, "Sender");
            serviceHost.AddServiceEndpoint("XchangeStreamer.Core.CacheServer.IRetriever", Settings.TcpBinding, "Retriever");

            serviceHost.AddServiceEndpoint("XchangeStreamer.Core.CacheServer.ISender", Settings.NamedPipeBinding, "Sender");
            serviceHost.AddServiceEndpoint("XchangeStreamer.Core.CacheServer.IRetriever", Settings.NamedPipeBinding, "Retriever");

            ServiceThrottlingBehavior throttling = new ServiceThrottlingBehavior();
            throttling.MaxConcurrentCalls = 100;
            throttling.MaxConcurrentInstances = 1;
            throttling.MaxConcurrentSessions = 1000;
            serviceHost.Description.Behaviors.Add(throttling);

            ServiceMetadataBehavior smb = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
            if (smb == null)
            {
                smb = new ServiceMetadataBehavior();
            }
            smb.HttpGetEnabled = true;
            serviceHost.Description.Behaviors.Add(smb);

            serviceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

            serviceHost.Open();
        }

        #endregion

        #region Public Properties

        public static Server Instance
        {
            get
            {
                if (server == null)
                {
                    lock (typeof(Server))
                    {
                        if (server == null)
                        {
                            server = new Server();
                        }
                    }
                }
                return server;
            }
        }

        public bool CollectPerformanceCounters
        {
            get;
            set;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.serviceHost.Close();
            this.engine.Dispose();
            server = null;
        }

        #endregion
    }
}
